#!/usr/bin/php
<?php

require_once dirname(__FILE__)  . '/simple_helpers.inc';

define('DOUBLE_QUOTES', 0x01);
define('SINGLE_QUOTES', 0x02);
define('BACKTICKS', 0x04);
define('BACKSLASH_ESCAPE', 0x08);
define('DOUBLE_ESCAPE', 0x10);
define('EXCLUDE_QUOTES', 0x20);




$languages = array('as' => DOUBLE_QUOTES|SINGLE_QUOTES|BACKSLASH_ESCAPE,
                   'c'=> DOUBLE_QUOTES|BACKSLASH_ESCAPE,
                   'csharp'=>DOUBLE_QUOTES|BACKSLASH_ESCAPE,                    
                   'css' => DOUBLE_QUOTES|SINGLE_QUOTES|BACKSLASH_ESCAPE,
                   'haskell' => DOUBLE_QUOTES|BACKSLASH_ESCAPE,
                   'java' => DOUBLE_QUOTES|BACKSLASH_ESCAPE,
                   'js' => DOUBLE_QUOTES|SINGLE_QUOTES|BACKSLASH_ESCAPE, 
                   'pascal' => DOUBLE_QUOTES|SINGLE_QUOTES|DOUBLE_ESCAPE,
                   'php' => DOUBLE_QUOTES|SINGLE_QUOTES|BACKTICKS|BACKSLASH_ESCAPE, 
                   'perl' => DOUBLE_QUOTES|SINGLE_QUOTES|BACKTICKS|BACKSLASH_ESCAPE,  
                   'python' => DOUBLE_QUOTES|SINGLE_QUOTES|BACKSLASH_ESCAPE, 
                   'ruby' => DOUBLE_QUOTES|SINGLE_QUOTES|BACKTICKS|BACKSLASH_ESCAPE, 
                   'sql_' => DOUBLE_QUOTES|BACKTICKS|BACKSLASH_ESCAPE, 
                   'sql' => DOUBLE_ESCAPE|SINGLE_QUOTES,
                   'vb' => DOUBLE_ESCAPE);
                   
$extra_languages['sql_'] = 'sql';
                             
$simple = array(
  '%D%D' => '',
  '%Dstring%D' => '',
  'A %DString%D' => 'A ',
  '%DString%D B' => ' B',
  '%DString1%D, %DString2%D' => ', '
  );
  
$escaped = array(
  '%D%ESC%D still inside%Dout_' => 'out_',
  '%D%ESC%ESC%Dout_' => 'out_'
  );

function expand_escapes($properties, $t, $char)
{
  $e = "";
  if ($properties & BACKSLASH_ESCAPE)
    $e = "\\";
  elseif($properties & DOUBLE_ESCAPE)
    $e = $char;
  else return false;
  
  return str_replace("%ESC", $e, $t);

}

function expand_quotes($properties, $tests)
{
  $new = array();
  
  foreach($tests as $i=>$o)
  {    
    $quotes = array(SINGLE_QUOTES=>"'",
    DOUBLE_QUOTES => '"',
    BACKTICKS => '`');
    foreach($quotes as $q=>$q_)
    {
      if ($properties & $q)
      {
        $in = str_replace("%D", $q_, $i);
        if ($properties & EXCLUDE_QUOTES)        
          $out = str_replace("%D", $q_, $o);
        else $out = str_replace("%D", "", $o);
        
        $in = expand_escapes($properties, $in, $q_);
        $out = expand_escapes($properties, $out, $q_);
        if ($in !== false && $out !== false)
          $new[$in] = $out;
        
      }
    }
  }
  return $new;
}







foreach($languages as $l=>$p)
{
  $tests = array_merge($simple, $escaped);
  
  $tests = expand_quotes($p, $tests);
  
  $python_ = ($l == 'python')? '|COMMENT' : ''; // python strings can be comments too.
  $css_ = ($l == 'css')? '|<.*?>' : ''; // CSS might capture other things as keywords or so
  
  // We are also testing backtick operators here which may be covered by
  // 'function' instead of string.
  foreach($tests as $in=>$out)
    test($l, $in, $out, "%<(STRING|FUNCTION$python_)>.*?</\\1>$css_%", '');
}


$rp_tests = array("$'" => "$'",
                  '$"' => '$"',
                  );

foreach(array('ruby', 'perl') as $l)
{
  foreach($rp_tests as $i=>$o)
  {
     test($l, $i, $o, '%</?(?!STRING).*?>%', '');
   }
}


exit($EXIT_STATUS);
